package com.example.algo.reverseLinkedListMToN;

/**
 * 反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
 *
 *  说明: 1 ≤ m ≤ n ≤ 链表长度。
 *
 *  示例:
 *
 *  输入: 1->2->3->4->5->NULL, m = 2, n = 4
 *  输出: 1->4->3->2->5->NULL
 *
 * @author zhoubin
 * @date 2020-07-13 10:01
 */
public class Solution {

    /**
     * 递归
     * 时间复杂度 O(n) n 个元素要递归 N 次
     * 空间复杂度 O(n) 由于使用递归，将会使用隐式栈空间。递归深度可能会达到 n 层。
     */
    public ListNode reverseListByRecursion(ListNode head) {
        // 当前节点为空 或 当前节点的后一个节点为空，表明这是最后一个节点不需要再递归
        if (head == null || head.next == null) {
            return head;
        }
        // 这里的 newNode 每次返回的都是最后一个节点，
        ListNode newNode = reverseListByRecursion(head.next);
        // 当前节点的下一节点的下一个节点指向当前节点，就相当于指针反转
        // 举例：假设当前 head = 4, head.next = 5, 5.next = null
        // reverseListByRecursion 调用 5.next 为空，所以会返回 5 也就是最后一个节点， newNode = 5
        // 此时，4.next = 5, 5.next = null, 那么将 4.next.next 指向 4，也就是 5.next = 4，这么一来就是反转了
        head.next.next = head;
        head.next = null;
        // 将最后一个 node 5 返回
        return newNode;
    }

    /**
     * 循环
     * 时间复杂度 O(n) n 个元素要递归 N 次
     * 空间复杂度 O(1) 整个循环过程中只创建了2个临时变量
     * @param m 起始位置
     * @param n 结束位置
     */
    public ListNode reverseListByWhile(ListNode head, int m, int n) {
        int index = 0;
        ListNode prev = null;
        while (head != null) {

            ListNode nxt = head.next;
            if (m <= index && index <= n) {
                head.next = prev;
                prev = head;
                head = nxt;
            } else {

            }

        }
        return prev;
    }

    static class ListNode {

        int val;
        ListNode next;

        ListNode(int x) {
            val = x;
        }
    }


    public static void main(String[] args) {
        // 构造数据
        ListNode l1 = new ListNode(1);
        ListNode l2 = new ListNode(2);
        ListNode l3 = new ListNode(3);
        ListNode l4 = new ListNode(4);
        ListNode l5 = new ListNode(5);

        l1.next = l2;
        l2.next = l3;
        l3.next = l4;
        l4.next = l5;

        Solution solution = new Solution();

        System.out.println("递归执行结果：");
        ListNode recursionNode = solution.reverseListByRecursion(l1);
        l1 = recursionNode;
        // 结果输出
        while (recursionNode != null) {
            System.out.println(recursionNode.val);
            recursionNode = recursionNode.next;
        }

        System.out.println();

        System.out.println("循环执行结果：");
        ListNode whileNode = solution.reverseListByWhile(l1,2,4);
        // 结果输出
        while (whileNode != null) {
            System.out.println(whileNode.val);
            whileNode = whileNode.next;
        }

    }
}

